#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <limits.h>

// 子进程：写入数据到管道
void writer(int wfd)
{
    sleep(5); // 等待 5 秒后再开始写入数据
    const char *str = "hello father, I am child";
    char buffer[128];
    int cnt = 0;
    pid_t pid = getpid(); // 获取当前进程 ID
    while (1)
    {
        sleep(1); // 每秒写入一个字符
        char c = 'A';
        write(wfd, &c, 1); // 向管道写入数据
        cnt++;

        printf("cnt: %d\n", cnt); // 打印写入计数
    }
    close(wfd); // 关闭写端
}

// 父进程：从管道读取数据
void reader(int rfd)
{
    char buffer[1024];
    int cnt = 10; // 限制读取次数
    while (1)
    {
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1); // 从管道读取数据
        if (n > 0)
            printf("father get a message: %s, n : %ld\n", buffer, n); // 打印读取到的数据
        else if (n == 0)
        {
            printf("read pipe done, read file done!\n"); // 管道已关闭
            break;
        }
        else
            break;

        cnt--; // 减少读取计数
        if (cnt == 0)
            break;
    }
    close(rfd); // 关闭读端
    printf("read endpoint close!\n");
}

int main()
{
    printf("PIPE_BUF: %d\n", PIPE_BUF); // 打印管道缓冲区大小
    // 创建管道
    int pipefd[2];
    int n = pipe(pipefd);
    if (n < 0)
        return 1;                                                                      // 创建失败
    printf("pipefd[0]: %d, pipefd[1]: %d\n", pipefd[0] /*read*/, pipefd[1] /*write*/); // 打印管道文件描述符

    // 创建子进程
    pid_t id = fork();
    if (id == 0)
    {
        // 子进程：写端
        close(pipefd[0]); // 关闭读端

        writer(pipefd[1]); // 调用写入函数

        exit(0); // 子进程退出
    }

    // 父进程：读端
    close(pipefd[1]); // 关闭写端

    reader(pipefd[0]); // 调用读取函数
    int status = 0;
    pid_t rid = waitpid(id, &status, 0); // 等待子进程结束
    if (rid == id)
    {
        printf("exit code: %d, exit signal: %d\n", WEXITSTATUS(status), status & 0x7F); // 打印子进程退出信息
    }

    return 0;
}